<template>
  <!-- 最外层容器 -->
  <div class="waterfall-select-container">
    <div class="waterfall-select-main">
      <div v-for="(item,index) in select" :class="{'active':index === queryParams.type}" class="select-item" @click="handleChangeSelect(index)">{{ item }}</div>
    </div>
  </div>
  <div id="waterfallContainer" class="waterfall-container">
    <!-- 里面的图片通过 js 来动态的生成 -->
    <div v-for="(item, index) in resourceList" :key="index" class="img-container">
      <img v-lazy="item.coverLink" :style="{ width: imgWidth  + 'px'}" alt="加载失败" @load="setPositions">
      <i :class="iconClass(item.resourceType)" class="iconfont "></i>
      <div :style="[generateRandomGradient()]" class="mask-container">
        <div class="title">{{ item.name }}</div>
        <button class="btn-13" @click="handlePreview(item)">查看详情</button>
      </div>
    </div>
    <div v-show="loading" class="loader">
      <div id="ld2">
        <div>
        </div>
        <div>
        </div>
        <div>
        </div>
        <div>
        </div>
        <div>
        </div>
        <div>
        </div>
        <div>
        </div>
      </div>
    </div>
    <div v-show="isNullData && resourceList" class="null">没有更多数据了</div>
  </div>
  <ModelPreview :model-url="modelUrl" :show-model="showModel" @close-model="showModel = false"/>
  <ImagePreview :image-url="imgUrl" :show="showImage" @close="showImage = false"/>
  <MarkDown :is-mark="isMark" :mark-down="markDown" @close-mark="isMark = false"/>
</template>

<script lang="ts" setup>
import {ref, onMounted, onBeforeUnmount, watch, Ref,} from 'vue';
import {getWaterfallList} from "@/api/request";
import ModelPreview from "@/components/ModelPreview/index.vue";
import ImagePreview from "@/components/ImagePreview/index.vue";
import MarkDown from "@/components/MarkDown/index.vue";
import {debounce} from "@/utils/util";


type ResourceArrayRef = Ref<{
  name: string;
  resourceType: number;
  coverLink: string;
  resourceLink: string;
}[]>;

const imgWidth = ref(390); // 图片宽度
const column = ref(5); // 列数
const resourceList: ResourceArrayRef = ref([]);
const queryParams = ref({  // 查询参数
  page: 1,
  size: 25,
  type: 0
})
let timeId: NodeJS.Timeout | null = null;
const showModel = ref(false) // 模型显示
const modelUrl = ref("") //模型数据
const showImage = ref(false)// 图片显示
const imgUrl = ref("") // 图片数据
const isMark = ref(false) // md数据
const markDown = ref("")
const loading = ref(false) // 加载效果
const isNullData = ref(false) // 是否没有数据了
const select = ref(["全部", "图片", "模型", "笔记", "项目", "视频"])
const initList = () => {
  loading.value = true
  getWaterfallList(queryParams.value).then(res => {
    if (res.data.length > 0) {
      resourceList.value = resourceList.value.concat(res.data)
    } else {
      isNullData.value = true
    }
    loading.value = false
  })
}

const iconClass = (type: number) => {
  if (type === 1) {
    return 'icon-shangchuantupian';
  } else if (type === 2) {
    return 'icon-jiandanmoxing';
  } else if (type === 3) {
    return 'icon-wenzhang';
  } else {
    return 'icon-xiangmuluyan'
  }
};

const handleChangeSelect = debounce((index: number) => {
  queryParams.value.type = index
  queryParams.value.page = 1
  isNullData.value = false
  resourceList.value = []
  initList()
}, 300)

// 预览函数
function handlePreview(item: any) {
  const {resourceType, resourceLink} = item
  const type = Number(resourceType)
  if (type === 1 || type === 4) { // 图片
    imgUrl.value = resourceLink
    showImage.value = true
  } else if (type === 2) { // 模型
    modelUrl.value = resourceLink
    showModel.value = true
  } else if (type === 3) { // 文本
    markDown.value = resourceLink
    isMark.value = true
  }
}


watch(resourceList, (newVal, oldVal) => {
  // 当 resourceList 值发生变化时重新计算图片位置
  if (newVal.length > 0) {
    setPositions();
  } else {
    const divContainer = document.getElementById('waterfallContainer');
    if (divContainer) {
      divContainer.style.height = "0"
    }
  }
});

onMounted(() => {
  if (navigator.userAgent.match(/(iPhone|Android|iPad)/i)) {
    column.value = 3
  }
  initList()
  const width = document.getElementById('waterfallContainer')?.clientWidth;
  if (width) {
    imgWidth.value = Math.floor(width / column.value - 20);
  }
  setPositions(); // 初始化设置图片位置
  bindEvent();
  const mainContainer = document.getElementById("main-container");
  if (mainContainer) {
    mainContainer.addEventListener('scroll', () => {
      const scrollHeight = mainContainer.scrollHeight;
      const clientHeight = mainContainer.clientHeight;
      const scrollTop = mainContainer.scrollTop;
      const scrollBottom = scrollHeight - (scrollTop + clientHeight);
      // 可自定义的阈值，当滚动到页面底部时剩余距离小于该值时触发操作
      const threshold = 1;
      if (scrollBottom < threshold && !isNullData.value) {
        queryParams.value.page += 1
        initList()
      }
    });
  }
});

onBeforeUnmount(() => {
  window.onresize = null;
});

function bindEvent() {
  window.onresize = () => {
    if (timeId) clearTimeout(timeId);
    timeId = setTimeout(() => {
      setPositions();
    }, 500);
  }
}

function setPositions() {
  const divContainer = document.getElementById('waterfallContainer');
  if (!divContainer) return;
  const containerWidth = divContainer.clientWidth;
  const columns = Math.floor(containerWidth / imgWidth.value);
  const gap = (containerWidth - columns * imgWidth.value) / (columns - 1); // 计算平均间隙
  const columnHeights = new Array(columns).fill(0);
  divContainer.querySelectorAll('.img-container').forEach((imgContainer: any, index) => {
    const columnIndex = columnHeights.indexOf(Math.min(...columnHeights)); // 找到高度最低的列索引
    const left = columnIndex * (imgWidth.value + gap); // 计算左边距
    const top = columnHeights[columnIndex];
    imgContainer.style.position = 'absolute';
    imgContainer.style.left = left + 'px';
    imgContainer.style.top = top + 'px';
    columnHeights[columnIndex] += imgContainer.offsetHeight + 20; // 加上间隙 使用gap计算的间隙布局会有问题 使用固定间隙
  });
  divContainer.style.height = Math.max(...columnHeights) - gap + 100 + 'px'; // 减去最后一行的间隙
}

function generateRandomGradient(): string {
  const MAX_ATTEMPTS = 10;
  // 生成随机颜色
  const randomColor = (): string => {
    const color: string = '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0');
    // 检查生成的颜色是否是合法的
    return /^#[0-9A-F]{6}$/i.test(color) ? color : randomColor(); // 如果颜色无效，则递归调用生成新颜色
  };
  // 生成随机渐变方向
  const directions: string[] = ['to right', 'to left', 'to top', 'to bottom', 'to top left', 'to top right', 'to bottom left', 'to bottom right'];
  const randomDirection: string = directions[Math.floor(Math.random() * directions.length)];
  // 生成起始颜色和结束颜色
  let startColor: string = '';
  let endColor: string = '';
  for (let i = 0; i < MAX_ATTEMPTS; i++) {
    startColor = randomColor();
    endColor = randomColor();
    // 如果颜色有效，则退出循环
    if (startColor !== '' && endColor !== '') {
      break;
    }
  }
  // 如果颜色无效，返回一个默认的渐变样式
  if (startColor === '' || endColor === '') {
    return 'background: linear-gradient(to right, #ffffff, #000000);'; // 默认渐变样式
  }
  console.log(`background: linear-gradient(${randomDirection}, ${startColor}, ${endColor});`)
  // 构建CSS渐变字符串
  return `background: linear-gradient(${randomDirection}, ${startColor}, ${endColor});`;
}

</script>

<style lang="scss" scoped>
.waterfall-select-container {
  margin-bottom: 50px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #36324a;

  .waterfall-select-main {
    padding: 5px;
    border-radius: 18px;
    display: flex;
    gap: 10px;
    color: #1c1f23;

    .select-item {
      padding: 6px 12px;
      cursor: pointer;
      border-radius: 25px;
      font-size: 15px;
      transition: all .5s;
      font-weight: bold;
      letter-spacing: 1px;
    }

    .active {
      background: #1c1f23;
      color: #f7f9fa;
    }
  }
}

.waterfall-container {
  width: 80%;
  height: 100%;
  margin: 0 auto;
  position: relative;
  padding-bottom: 50px;
}

.img-container {
  transition: all 0.3s;
  position: relative;

  &:hover .iconfont {
    opacity: 0;
  }

  .iconfont {
    position: absolute;
    right: 15px;
    top: 15px;
    font-size: 20px;
    font-weight: bold;
    text-shadow: 2px 2px 4px rgba(0, 0, 0, .5);
    color: #ffffff;
    transition: all 1s;
  }

  .mask-container {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    transform: rotateY(-180deg);
    transition-timing-function: cubic-bezier(.175, .885, .32, 1.275);
    transition-duration: .5s;
    transition-property: transform, opacity;
    border-radius: 6px;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    font-family: "宋体", serif;
    background: linear-gradient(to right, rgb(171, 236, 174), rgb(194, 152, 196));

    .title {
      width: 80%;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      text-align: center;
    }

  }

  &:hover img {
    transform: rotateY(180deg);
    opacity: 0;
  }

  &:hover .mask-container {
    transform: rotateY(0);
    opacity: 1;
  }

  img {
    border-radius: 6px;
    cursor: pointer;
    transition-timing-function: cubic-bezier(.175, .885, .32, 1.275);
    transition-duration: .5s;
    transition-property: transform, opacity;
    box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 18px 0px
  }
}

/* 13 */
.btn-13 {
  margin-top: 20px;
  border: none;
  z-index: 1;
  border-radius: 25px;
  padding: 10px 30px;
  font-weight: bold;
  font-size: 14px;
  letter-spacing: 3px;
  transition: all .5s;
  position: relative;
  display: inline-block;
  color: white;
  background-color: #f77ade;
  font-family: "宋体", serif;

  &:hover {
    background-color: #36324a;
  }
}


.loader {
  position: absolute;
  bottom: 30px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.null {
  position: absolute;
  bottom: 30px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: #2c3051;
  font-size: 18px;
  font-weight: bold;
  font-family: "宋体", serif;
  letter-spacing: 1px;
}

#ld2 {
  display: flex;
  flex-direction: row;
}

#ld2 div {
  height: 20px;
  width: 5px;
  background: #FE4A49;
  margin: 3px;
  border-radius: 25px;
}

#ld2 div:nth-child(1) {
  animation: ld2 1s ease-in-out infinite 0s;
}

#ld2 div:nth-child(2) {
  animation: ld2 1s ease-in-out infinite 0.1s;
}

#ld2 div:nth-child(3) {
  animation: ld2 1s ease-in-out infinite 0.2s;
}

#ld2 div:nth-child(4) {
  animation: ld2 1s ease-in-out infinite 0.3s;
}

#ld2 div:nth-child(5) {
  animation: ld2 1s ease-in-out infinite 0.4s;
}

#ld2 div:nth-child(6) {
  animation: ld2 1s ease-in-out infinite 0.5s;
}

#ld2 div:nth-child(7) {
  animation: ld2 1s ease-in-out infinite 0.6s;
}

@keyframes ld2 {
  0% {
    transform: scaleY(1);
    background: #FED766;
  }
  25% {
    background: #009FB7;
  }
  50% {
    transform: scaleY(2);
    background: #59CD90;
  }
  75% {
    background: #FE4A49;
  }
  100% {
    transform: scaleY(1);
    background: #D91E36;
  }
}
</style>
